#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <functional>

#include "mutex.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "log.hpp"
#include "threadpool.hpp"
#include "Socket.hpp"


#define BACKLOG 8

namespace TcpServerModule
{
    using namespace SocketModule;
    using namespace LockModule;
    using namespace LogModule;
    using namespace ThreadPoolModule;
    static const uint16_t gport = 8080;
    //using handler_t = std::function<std::string(std::string)>;
    using handler_t = std::function<void(SockPtr,InetAddr)>;
    class TcpServer
    {
    public:
        // TcpServer(handler_t handler, int port = gport)
        //     : _handler(handler), _port(port), _isrunning(false)
        // {
        TcpServer(int port)
        :_port(port)
        ,_listensock(std::make_unique<TcpSocket>())
        ,_isrunning(false)
        {}
        void InitServer(handler_t func)
        {
            _handler = func;
            _listensock->BuildTcpSocketMethod(_port);
            // // socket    
            // _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
            // if (_listensockfd < 0)
            // {
            //     LOG(FATAL) << "socket failed";
            //     Die(SOCKET_ERR);
            // }
            // LOG(INFO) << "socket success,sockfd is: " << _listensockfd;
            // struct sockaddr_in local;
            // bzero(&local, sizeof(local));
            // local.sin_family = AF_INET;
            // local.sin_port = ::htons(gport);
            // local.sin_addr.s_addr = INADDR_ANY;

            // // bind
            // int n = ::bind(_listensockfd, CONV(&local), sizeof(local));
            // if (n < 0)
            // {
            //     LOG(FATAL) << "bind failed";
            //     Die(BIND_ERR);
            // }
            // LOG(INFO) << "bind success,sockfd is: " << _listensockfd;

            // n = ::listen(_listensockfd, BACKLOG);
            // if (n < 0)
            // {
            //     LOG(FATAL) << "listen failed";
            //     Die(LISTEN_ERR);
            // }
            // LOG(INFO) << "listen success,sockfd is: " << _listensockfd;
        }
        // 处理任务
        // void HandlerRequest(int sockfd)
        // {
        //     LOG(INFO) << "deal HandlerRequest,sockfd is " << sockfd;
        //     char inbuffer[4096];
        //     while (true)
        //     {
        //         ssize_t n = ::recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0);
        //         if (n > 0)
        //         {
        //             inbuffer[n] = 0;
        //             LOG(INFO) << inbuffer;
        //             // std::string echo_str = "server echo# ";
        //             // echo_str += inbuffer;
        //             // ::send(sockfd, echo_str.c_str(), echo_str.size(), 0);
        //             handler_t(inbuffer);
        //         }
        //         else if (n == 0)
        //         {
        //             LOG(INFO) << "client quit";
        //             break;
        //         }
        //         else
        //         {
        //             LOG(ERROR) << "recv失败,线程退出";
        //             break;
        //         }
        //     }
        // }
        void Handler(SockPtr sock,InetAddr addr)
        {
            _handler(sock,addr);
        }

        void Start()
        {
            _isrunning = true;
            while(_isrunning)
            {
                InetAddr clientaddr;
                auto sock = _listensock->Accept(&clientaddr);
                if(sock == nullptr)
                    continue;
                LOG(DEBUG) <<"accept a client: "<<clientaddr.Addr();
                ThreadPool<std::function<void(std::string)>>::GetInstance()->Enqueue(
                    [this,sock,clientaddr](std::string){this->Handler(sock,clientaddr);}
                );
            }
            // _isrunning = true;
            // while (_isrunning)
            // {
            //     // 获取链接
            //     struct sockaddr_in peer;
            //     socklen_t len = sizeof(peer);

            //     int sockfd = ::accept(_listensockfd, CONV(&peer), &len);
            //     if (sockfd < 0)
            //     {
            //         LOG(WARNING) << "accept error";
            //         continue;
            //     }
            //     LOG(INFO) << "accept success,socket is: " << sockfd;
            //     InetAddr addr(peer);
            //     LOG(INFO) << "client: " << addr.Addr();

            //     // 发送任务
            //     // 1.多进程
            //     //  pid_t pid = fork();
            //     //  if(pid == 0)
            //     //  {
            //     //      if(fork()>0)
            //     //          exit(0);//孙子进程->孤儿进程 相当于分离
            //     //      HandlerRequest(sockfd);
            //     //      exit(0);
            //     //  }
            //     //  waitpid(pid,nullptr,0);
            //     //  ::close(sockfd);

            //     //2.多线程 - 线程池
            //     ThreadPool<std::function<void(std::string)>>::GetInstance()->Enqueue([this, sockfd](std::string name)
            //                                                                    {LOG(INFO)<<name<<": 开始处理 HandlerRequest";
            //                                                                     this->HandlerRequest(sockfd); });                                                          
            // }
        }
        void Stop()
        {
            _isrunning = false;
        }
        ~TcpServer()
        {
        }

    private:
        //int _listensockfd; // 监听套接字
        std::unique_ptr<TcpSocket> _listensock;
        uint16_t _port;
        bool _isrunning;
        handler_t _handler;
    };
}